/**
 * 包围盒计算器：封装包围盒计算代码
 *
 * 用以代替以下代码模式:
 *   const box3 = new THREE.Box3()
 *   const size = new THREE.Vector3()
 *   const center = new THREE.Vector3()
 *
 *   box3.setFromObject(object)
 *   box3.getCenter(center)
 *   box3.getSize(size)
 *
 *   selectedBox.position.copy(center)
 *   selectedBox.scale.copy(size)
 *
 * 可简化为:
 *   import { boundingCalculator } from '@/three/BoundingCalculator'
 *   boundingCalculator.calculate(object)
 *   boundingCalculator.writeToBoxObject(selectedBox)
 */
import * as THREE from 'three';

// 归一化变换
function normalizeTransform(object: THREE.Object3D) {
  object.position.set(0, 0, 0);
  object.rotation.set(0, 0, 0, THREE.Euler.DEFAULT_ORDER);
  object.scale.set(1, 1, 1);
}

export class BoundingCalculator {
  box3 = new THREE.Box3();
  size = new THREE.Vector3();
  center = new THREE.Vector3();

  // 主函数：计算包围盒
  calculate(object: THREE.Object3D) {
    this.box3.setFromObject(object);
    this.box3.getCenter(this.center);
    this.box3.getSize(this.size);
  }

  // 主函数：计算包围盒（从父节点剥离，并撤销自身变换）
  calculateWithoutTransform(object: THREE.Object3D) {
    const objectClone = object.clone(); // 克隆就会从父节点剥离
    normalizeTransform(objectClone);
    this.calculate(objectClone);
  }

  // 主函数：重置为空（在使用 expand 前必须先调用）
  reset() {
    this.box3.makeEmpty();
    this.box3.getCenter(this.center);
    this.box3.getSize(this.size);
  }

  // 主函数：扩展包围盒
  expand(object: THREE.Object3D) {
    this.box3.expandByObject(object);
    this.box3.getCenter(this.center);
    this.box3.getSize(this.size);
  }

  // 输出到包围盒物体
  writeToBoxObject(object: THREE.Object3D) {
    object.position.copy(this.center);
    object.scale.copy(this.size);
  }

  // 输出结果（中心、大小）
  writeCenterAndSize(center: THREE.Vector3, size: THREE.Vector3) {
    center.copy(this.center);
    size.copy(this.size);
  }

  // 输出中心
  writeCenter(center: THREE.Vector3) {
    center.copy(this.center);
  }

  // 输出大小
  writeSize(size: THREE.Vector3) {
    size.copy(this.size);
  }
}

// 全局唯一的单例
export const boundingCalculator = new BoundingCalculator();
